<template>
  <div :class="animate" :style="{ height: height, width: width }" :id="chartOption.bindingDiv">
    <ul :style="{ height: height, width: width}" class="tabul"  ref="text">
      <li class="tabli" :style="liWidth" v-for="(item,index) in tabValue" @click="changeLi(index)" :key="index"  @mouseenter="pause" @mouseleave="start">
        <div class="tabBorder" :style="index == selectedIndex?(chartOption.selectedBGFlag == 'img'? selectedImgStyle:selectedBorderStyle):(chartOption.normalBGFlag == 'img'?normalImgStyle:normalBorderStyle)">
          <div class="tabText" :style="index == selectedIndex?selectedTextStyle:normalTextStyle">
            {{item.content}}
          </div>
        </div>
      </li>
    </ul>
  </div>
  
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from '@/views/dashboard/mixins/resize'
import VueEvent from '@/views/tool/datav/VueEvent'
import '../../animate/animate.css'

import {parseQueryString, fIsUrL} from '../../util/urlUtil'
import { websocketCommand } from "../../util/websocket.js";
import { remoteTabApi,chartApiBar } from "@/api/tool/datav/chartApi";
const animationDuration = 6000;

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "100%",
    },
    chartOption: {
      type: Object,
    },
    drawingList:{
      type: Array
    }
  },
  data() {
    return {
      chart: null,
      selectedIndex:0,
      tabValue:[],
      //dataOption: this.chartOption,
      carouselTimer: '',
      timer:'',
      controlWsObj: null,
      controlWsFlag: false,
      controlWsTimer: "",
      wsObj: null,
      wsFlag: false,
      wsTimer: "",
      wsValue: null,
      animate: this.className
    };
  },
  watch: {
    width() {
      
    },
    height() {
      
    },
    chartOption: {
      deep: true,
      handler(newVal) {
        this.setOptions(JSON.parse(JSON.stringify(newVal)));
      }
    },
    'chartOption.dur': {
      handler() {
        this.rotationChart();
      }
    },
    'chartOption.isRotation': {
      handler() {
        this.rotationChart();
      }
    },
    "chartOption.timeout": {
      handler() {
        this.chart = null;
        this.initChart();
      }
    },
    "chartOption.dataSourceType": {
      handler(value) {
        if (value !== "websocket") {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if (value !== "url") {
          clearTimeout(this.timer);
        }
      }
    },
    "chartOption.isControl": {
      handler(value) {
        //切换数据源重新连接
        if (!value) {
          this.controlWsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
      }
    },
    "chartOption.controlKey": {
      handler(newValue, oldValue) {
        //删除键值断开连接
        if((oldValue !== undefined && oldValue != "" )&& (newValue == undefined || newValue == "")){
          this.controlWsFlag = false;
         
        }
        this.animate = this.className;
      }
    },
    "chartOption.interfaceKey": {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if (oldValue !== undefined && oldValue != "") {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    controlWsFlag: {
      handler(value) {
        if (!value) {
          this.controlCloseWs();
        }
      }
    },
    wsFlag: {
      handler(value) {
        if (!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value) {
        this.animate = value;
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart = null;
    clearTimeout(this.carouselTimer);
    clearTimeout(this.timer);
    if (this.controlWsFlag) {
      this.controlCloseWs();
    }
    if (this.wsFlag) {
      this.closeWs();
    }
  },
  computed:{
    normalBorderStyle(){
      const style = {
        borderWidth:this.chartOption.borderWidth + "px",
        borderColor:this.chartOption.borderColor,
        backgroundColor: this.chartOption.backgroundColor, 
      };
      return style
    },
    selectedBorderStyle(){
      const style = {
        borderWidth:this.chartOption.selectedBorderWidth + "px",
        borderColor:this.chartOption.selectedBorderColor,
        backgroundColor: this.chartOption.selectedBackgroundColor, 
      };
      return style
    },
    normalTextStyle(){
      const style = {color:this.chartOption.fontColor,fontSize:this.chartOption.fontSize + "px",fontFamily:this.chartOption.fontFamily,
        fontWeight:this.chartOption.fontWeight,letterSpacing:this.chartOption.letterSpacing + "px",textAlign:this.chartOption.textAlign}
      return style
    },
    selectedTextStyle(){
      const style = {color:this.chartOption.selectedFontColor,fontSize:this.chartOption.selectedFontSize + "px",fontFamily:this.chartOption.selectedFontFamily,
        fontWeight:this.chartOption.selectedFontWeight,letterSpacing:this.chartOption.selectedLetterSpacing + "px",textAlign:this.chartOption.textAlign}
      return style
    },
    normalImgStyle(){
      const style = {
        borderWidth:'0px',
        borderColor:'',
        backgroundColor: '', 
        backgroundImage: `url(${this.chartOption.normalTabBG}) `,
        backgroundRepeat : 'no-repeat',
        backgroundSize : '100% 100%',
        //animation: 'fade 2s ease-in' 
      };
      return style
    },
    selectedImgStyle(){
      const style = {
        borderWidth:'0px',
        borderColor:'',
        backgroundColor: '',
        backgroundImage:`url(${this.chartOption.selectedTabBG}) `,
        backgroundRepeat : 'no-repeat',
        backgroundSize : '100% 100%',
        //animation: 'fade 2s ease-in'
      };
      return style
    },
    liWidth(){

      const num = this.chartOption.staticDataValue.length;
      let style = {};

      if(this.chartOption.direction == 'vertical'){
          style = {width: 100 + '%',height:100/num + "%"};
      }else{
          style = {height: 100 + '%',width:100/num + "%"};
      }     
      //console.log("width:" + parseInt(100/num) + "%");
      return style
    }
  },
  methods: {
    initChart() {
      
       
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if (this.timer != "") {
        clearTimeout(this.timer);
      }
      if (
        (this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') &&
        this.chartOption.timeout > 0
      ) {
        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
          this.timer = setTimeout(() => {
           
            timerTask();
          }, this.chartOption.timeout);
        };

        timerTask();
      }else{
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
      
    },
    setOptions: async function(dataOption) {
      //初始化数据
      //如果不是静态数据就调用接口给staticDataValue赋值
      if (dataOption.dataSourceType == "url" || dataOption.isStaticData == false) {
        let paramJson = parseQueryString(dataOption.requestParameters);

        let interfaceURL = dataOption.interfaceURL;

        let result = await chartApiBar(
          dataOption.requestMethod,
          interfaceURL,
          paramJson,
          dataOption.token
        );
        dataOption.staticDataValue = result;

      } else if (dataOption.dataSourceType == "database") {
      } else if (dataOption.dataSourceType == "websocket") {
        if (
          dataOption.interfaceKey != undefined &&
          dataOption.interfaceKey != ""
        ) {
          if (!this.wsFlag) {
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs();
          }
          if (this.wsValue != null) {
            dataOption.staticDataValue = this.wsValue;
          }
        }
      }
      this.tabValue = dataOption.staticDataValue;
      //数据处理
       if(dataOption.customData != undefined && dataOption.customData != ""){
          this.$nextTick(() => {

            try {
              dataOption.staticDataValue = (
               //里面为要处理的代码块 
                eval(dataOption.customData) 
              
              )(
                dataOption.staticDataValue,
                this.$refs.text
              );
              this.tabValue = dataOption.staticDataValue;
            } catch (error) {
              console.log(error)
            }
              
          })
       }
       
       //交互组件配置
       if(dataOption.interactData != undefined && dataOption.interactData != ""){
          this.$nextTick(() => {

            try {
              dataOption.staticDataValue = (
               //里面为要处理的代码块 
                eval(dataOption.interactData) 
              
              )(
                dataOption.staticDataValue,
                this.$refs.text
              );
              this.tabValue = dataOption.staticDataValue;
            } catch (error) {
              console.log(error)
            }
              
          })
       }

        

      if(dataOption.isControl == true){
        if (dataOption.controlKey != undefined &&dataOption.controlKey != "") {
          if (!this.controlWsFlag) {
            this.controlWsFlag = true;
            this.controlCreateWs();
          }else{
            this.controlCloseWs();
            this.controlCreateWs();
          }
        }
      }
      

      this.changeLi(0);
      this.rotationChart();
     
    },
    changeLi(index){

      this.selectedIndex = index;

      //如果开启了远程控制
      if(this.chartOption.isRemote === true && this.chartOption.remoteKey !== undefined && this.chartOption.remoteKey !== ''){
        
        let remoteData = {};
        
        let selectObj = this.chartOption.staticDataValue[index];
        remoteData.result = selectObj;
        remoteData.key = this.chartOption.remoteKey;

        remoteTabApi(remoteData);

      }


      //先将所有组件设置为显示状态
      // this.drawingList.forEach(element => {
      //       element.isShow = true;                   
      // });
      
      const chartList = this.drawingList;
      if(chartList != null){
        const tabList = [];
        //获取当前选中绑定tab id
        const bindingObj = this.chartOption.staticDataValue[index];
        
      
        if(this.chartOption.bindingObjs.length > 0){
          //将所有绑定组件设置隐藏
          for(const obj of this.chartOption.bindingObjs){
            //判断如果新版选项卡则循环获取绑定的多个组件
            if(typeof obj.chartids != "undefined" && obj.chartids != '' ){
              
              obj.chartids.forEach(element => {
                const chart =  chartList.filter(function (item) {
                  return item.customId == element && obj.bindid != null;
                })[0]
                if(chart != null){
                    tabList.push({customId:chart.customId,isShow:false})
                }        
              });

            }
            //旧版选项卡按照原来方式获取绑定的单个组件
            else{
               
                const chart =  chartList.filter(function (item) {
                  return item.customId == obj.chartid && obj.bindid != null;
                })[0]
                if(chart != null){
                    tabList.push({customId:chart.customId,isShow:false})
                }        
             
            }
             
          } 
          
          // 根据绑定tab id 获取 bindingObjs对应对象
          const bindObj = this.chartOption.bindingObjs.filter(function(item){
            return item.bindid == bindingObj.bindid;
          })[0]
            
          if(bindObj != null){
            //在tabList中将选中组件设置为显示
            //判断如果是新版选项卡，则循环获取绑定的组件
            if(typeof bindObj.chartids != "undefined" && bindObj.chartids != ''){
              
              bindObj.chartids.forEach(element => {
                const selectedChart = tabList.filter(function (item) {         
                  return item.customId ==element;
                })[0] 
                if(selectedChart != null){
                  selectedChart.isShow = true;                             
                }  
              });
              
            }
            //旧版选项卡按照原来方式获取绑定组件
            else{
              const selectedChart = tabList.filter(function (item) {         
                return item.customId == bindObj.chartid;
              })[0]   
              if(selectedChart != null){
                selectedChart.isShow = true;                            
              }  
            }
                       
          }

          if(tabList != null){
            //向父组件发送事件，同步修改drawinglist            
            VueEvent.$emit('tabchange',tabList)  
          }
                  
        }
      }
      
    },
    
    rotationChart(){
      //判断是否开启定时器，选择开启轮播并且dur不为0时候开启定时器
      if(this.carouselTimer != '') {
        clearTimeout(this.carouselTimer);
      }
      if(this.chartOption.isRotation == true && this.chartOption.dur > 0) {
       
        let rotationIndex = 0;
        let timerTask = () => {
          this.changeLi(rotationIndex);
          rotationIndex ++ ;
          if(rotationIndex == this.chartOption.staticDataValue.length){
            rotationIndex = 0;
          }
          this.carouselTimer = setTimeout(() => {
            timerTask();
          }, this.chartOption.dur);
        }

        timerTask();
      }
    },
    start(){
      if(this.chartOption.isRotation == true && this.chartOption.dur > 0) {
       
        let rotationIndex = this.selectedIndex;
        let timerTask = () => {
          this.changeLi(rotationIndex);
          rotationIndex ++ ;
          if(rotationIndex == this.chartOption.staticDataValue.length){
            rotationIndex = 0;
          }
          this.carouselTimer = setTimeout(() => {
            timerTask();
          }, this.chartOption.dur);
        }

        timerTask();
      }
    },
    pause(){
      if(this.chartOption.isRotation == true && this.chartOption.dur > 0) {
        clearTimeout(this.carouselTimer);
      }
    },
    //  ws连接成功，后台返回的ws数据
    controlReceiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        let selectValue = JSON.parse(e.result);
        for(var i=0;i<this.chartOption.staticDataValue.length;i++){
          if(this.chartOption.staticDataValue[i].bindid == selectValue.bindid){
            this.changeLi(i)
          }

        }
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    controlCreateWs() {
      this.controlWsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.controlWsObj,
        "create",
        5000,
        this.chartOption.controlKey,
        this.controlSendHeartBeat,
        this.controlReceiveMsg,
        this.controlReconnectWs,
        this.controlWsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    controlReconnectWs() {
      if (this.controlWsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.controlCreateWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    controlSendHeartBeat() {
      if (this.controlWsTimer != "") {
        clearTimeout(this.controlWsTimer);
      }

      let controlWsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.controlKey };
        this.controlWsObj.send(JSON.stringify(obj));
        this.controlWsTimer = setTimeout(() => {
          controlWsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.controlWsWarning();
      };
      controlWsTimerTask();
    },

    controlWsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.controlWsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.controlWsTimer);
      }
    },
    controlCloseWs() {
      clearTimeout(this.controlWsTimer);
      websocketCommand(
        this.controlWsObj,
        "close",
        5000,
        this.chartOption.controlKey,
        this.controlSendHeartBeat,
        this.controlReceiveMsg,
        this.controlReconnectWs,
        this.controlWsWarning
      );
      this.controlWsObj = null;
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        this.wsValue = e.result;
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs() {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.wsObj,
        "create",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    reconnectWs() {
      if (this.wsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat() {
      if (this.wsTimer != "") {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.interfaceKey };
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      };

      wsTimerTask();
    },
    wsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.wsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.wsTimer);
      }
    },
    closeWs() {
      clearTimeout(this.wsTimer);
      websocketCommand(
        this.wsObj,
        "close",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
      this.wsObj = null;
    }
  }
};
</script>
<style ang="scss" scoped>
.tabBorder{
	border-style: solid;
	height: 100%;
	position: relative;
}
.tabText{
	position: absolute;
  top : 38%;
  width: 100%;
}
.tabli{
  list-style: none; 
  padding-left: 1px;
  float: left;
  cursor: default;
}
.tabul{
  position:relative;
  list-style: none;
  margin:0; 
  padding:0; 
}
.fade-enter-active, .fade-leave-active {
    transition: opacity 2s
}
.fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ {
    opacity: 0
}
</style>
